001    /*
002     * Copyright 2005 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.transit.local;
020    
021    import java.io.IOException;
022    import java.io.InputStream;
023    import java.io.FileInputStream;
024    import java.io.OutputStream;
025    import java.io.FileOutputStream;
026    import java.io.File;
027    import java.net.URL;
028    import java.net.URLConnection;
029    import java.security.AccessController;
030    import java.security.PrivilegedExceptionAction;
031    import java.security.PrivilegedActionException;
032    import java.security.PrivilegedAction;
033    
034    import net.dpml.transit.Transit;
035    import net.dpml.transit.Artifact;
036    
037    /**
038     * The local URL protocol connection implementation.
039     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
040     * @version 1.0.1
041     */
042    public class LocalURLConnection extends URLConnection
043    {
044        private boolean m_connected;
045    
046        private File m_target;
047    
048        /**
049         * Creation of a new local handler.
050         * @param url the url to establish a connection with
051         * @exception NullPointerException if the url argument is null
052         */
053        LocalURLConnection( URL url )
054            throws NullPointerException
055        {
056            super( url );
057    
058            m_connected = false;
059        }
060    
061       /**
062        * Establish a connection.
063        *
064        * @exception IOException is an error occurs while attempting to establish
065        *  the connection.
066        */
067        public void connect()
068            throws IOException
069        {
070            if( m_connected )
071            {
072                return;
073            }
074    
075            m_connected = true;
076            
077            try
078            {
079                AccessController.doPrivileged( 
080                  new PrivilegedExceptionAction()
081                  {
082                    public Object run()
083                        throws IOException
084                    {
085                        String spec = url.toExternalForm();
086                        try
087                        {
088                            Artifact artifact = Artifact.createArtifact( spec );
089                            String groupSpec = artifact.getGroup();
090                            String artifactName = artifact.getName();
091                            String typeSpec = artifact.getType();
092                            String versionSpec = artifact.getVersion();
093                            File prefs = Transit.DPML_PREFS;
094                            File group = new File( prefs, groupSpec );
095                            File type = new File( group, typeSpec + "s" );
096                            if( null == versionSpec )
097                            {
098                                final String filename = artifactName + "." + typeSpec;
099                                m_target = new File( type, filename );
100                            }
101                            else
102                            {
103                                final String filename = artifactName + "-" + versionSpec + "." + typeSpec;
104                                m_target = new File( type, filename );
105                            }
106                        }
107                        catch( Throwable e )
108                        {
109                            String message = e.getMessage();
110                            IOException exception = new IOException( message );
111                            exception.initCause( e.getCause() );
112                            throw exception;
113                        }
114                        return null; // nothing to return
115                    }
116                  }
117                );
118            } 
119            catch( PrivilegedActionException e )
120            {
121                throw (IOException) e.getException();
122            } 
123        }
124    
125       /**
126        * Return an input stream to the resource.
127        * @return the input stream
128        * @exception IOException is an error occurs
129        */
130        public InputStream getInputStream()
131            throws IOException
132        {
133            connect();
134            if( m_target == null )
135            {
136                return null;
137            }
138            else
139            {
140                return new FileInputStream( m_target );
141            }
142        }
143    
144       /**
145        * Return an output stream to the resource.
146        * @return the output stream
147        * @exception IOException if any I/O problems occur.
148        */
149        public OutputStream getOutputStream()
150            throws IOException
151        {
152            connect();
153            if( m_target == null )
154            {
155                return null;
156            }
157            else
158            {
159                if( !m_target.exists() )
160                {
161                    File parent = m_target.getParentFile();
162                    if( null != parent )
163                    {
164                        parent.mkdirs();
165                    }
166                    m_target.createNewFile();
167                }
168                return new FileOutputStream( m_target );
169            }
170        }
171    
172       /**
173        * Return the content for this local resource.
174        * @param classes a sequence of classes against which the
175        *   implementation will attempt to establish a known match
176        * @return the content object (possibly null)
177        * @exception IOException is an error occurs
178        */
179        public Object getContent( final Class[] classes )
180            throws IOException
181        {
182            connect();
183            Object result = AccessController.doPrivileged( 
184              new PrivilegedAction()
185              {
186                public Object run()
187                {
188                    for( int i=0; i < classes.length; i++ )
189                    {
190                        Class c = classes[i];
191                        if( c.equals( File.class ) )
192                        {
193                            return m_target;
194                        }
195                    }
196                    return null;
197                }
198              }
199            );
200    
201            if( null != result )
202            {
203                return result;
204            }
205            else
206            {
207                if( null != m_target )
208                {
209                    return m_target.toURL().getContent( classes );
210                }
211                else
212                {
213                    return super.getContent( classes );
214                }
215            }
216        }
217    }